#include "cc9d.h"
#include "crc8.h"

static const byte SEPARATOR = 0x9d;//分隔符
static const byte ESCAPE = 0x9e;//转义字符
static const byte ESC_9D = 0xfe;//9D转义目标
static const byte ESC_9E = 0xff;//9E转义目标



// 	发送相关的程序
static void sendByte(byte b);
static byte send_crc;//发送的CRC
void cc9d_startSend(uint8 from_port,	uint8 to_port,	uint16 remote_addr){	
		_cc9d_sendByte(SEPARATOR);
		send_crc = 0xff;//第一步，发送前先将发送的CRC初始化为0xff
		sendByte(from_port);
		sendByte(to_port);
		sendByte((byte)(remote_addr>>0));
		sendByte((byte)(remote_addr>>8));
}
void cc9d_sendData(byte b){
	sendByte(b);
}	
void cc9d_finishSend(){
	sendByte(send_crc);//第三步，所有数据发送完毕后，send_crc中的数据就是CRC结果
	_cc9d_sendByte(SEPARATOR);	
}		
static void sendByte(byte b) {
	crcInput(send_crc,b);//第二步，b是待计算的数据，将数据送入CRC计算器
	if (b == SEPARATOR) {
		_cc9d_sendByte(ESCAPE);
		_cc9d_sendByte(ESC_9D);
	} else if (b == ESCAPE) {
		_cc9d_sendByte(ESCAPE);
		_cc9d_sendByte(ESC_9E);
	} else {
		_cc9d_sendByte(b);
	}
}
	
// 	接收相关的程序	
#define Abandon 127
static byte xdata recv_buf[128];
static int8 recv_ptr = 0;
static byte recv_crc = 0xff;	

static void recvData(byte b) {
	if (recv_ptr > Abandon) {//如果收数据量超过了缓冲区，会将数据堆放在接收缓冲的127位置
		recv_ptr = Abandon;//通常这是「总线错误」、「插拔造成误码或」或者「错过包头」造成的
	}
	crcInput(recv_crc,b);
	recv_buf[recv_ptr] = b;
	recv_ptr++;
}
static void recvEnd() {
	if (recv_ptr > 5) {//必须收到4个地址参数加一个CRC
		if (recv_crc != 0) {//crc 错误
			
		} else {
			//包缓冲区为空了，
			_cc9d_receivePkg(recv_buf,recv_ptr);
		}
	}
	//继续收下一个包
	recv_ptr = 0;
	recv_crc = 0xff;
}

//9D FE 和9D FF 分别表示9D和9E，
//9D 后面跟其他数字则会被识别为特殊的单byte命令，通常用作传输控制和测试。
static void recvEsc(byte b) {
	//在Chhol模块的应用中，不会用到这一功能。
}		
#define YES 1
#define NO 0
static uint8 is_in_esc = NO;
void cc9d_recvbyte(byte b) {
	if (is_in_esc==YES) {
		is_in_esc = NO;
		if (b >= 0xfe) {
			recvData((byte)(b - ESC_9D + SEPARATOR));//b = 0xfe => 9D ; b = 0xff => 9E
		} else {
			recvEsc(b);
		}
	} else {
		if (b == SEPARATOR) {
			recvEnd();
		} else if (b == ESCAPE) {
			is_in_esc = YES;
		} else {
			recvData(b);
		}
	}
}
void cc9d_init(){
	recv_ptr = 0;	
	is_in_esc = NO;
}	


